package com.hailiao.beidou.message.bd.ble

import com.d10ng.common.base.toStringWithMaxDecimal
import com.d10ng.common.coordinate.toLatitudeString
import com.d10ng.common.coordinate.toLongitudeString
import com.hailiao.beidou.comm.bluetooth.BLEHub
import com.hailiao.beidou.comm.bluetooth.constant.BLEStatus
import com.hailiao.beidou.comm.bluetooth.data.NotifySettingInfo
import com.hailiao.beidou.core.BDCore
import com.hailiao.beidou.message.bd.Beidou
import com.hailiao.beidou.message.bd.R
import com.hailiao.beidou.message.bd.constant.ProtoVersion
import com.hailiao.beidou.message.bd.data.BDDeviceStatusData
import com.hailiao.beidou.message.bd.data.toBDDeviceStatusDataList
import com.hailiao.beidou.privatexchy.BDZJA_Data
import com.hailiao.beidou.privatexchy.CCDWO_Data
import com.hailiao.beidou.privatexchy.CCLFN_Data
import com.hailiao.beidou.privatexchy.CCZJA_Data
import com.hailiao.beidou.privatexchy.sendCCDWO
import com.hailiao.beidou.privatexchy.sendCCLFN
import com.hailiao.beidou.privatexchy.sendCCZJA
import com.hailiao.beidou.standard3.BDGGA_Data
import com.hailiao.beidou.standard3.constant.BDSendChannel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch

/**
 * 基础H130X设备
 * @Author d10ng
 * @Date 2023/12/12 14:32
 */
abstract class H130XDevice : IBLEDevice {

    // 定时自检任务
    private var checkSelfJob: Job? = null

    // 自检数据
    private val checkSelfDataFlow = MutableStateFlow<BDZJA_Data?>(null)

    // 定位数据
    private val locationDataFlow = MutableStateFlow<BDGGA_Data?>(null)

    init {
        val scope = CoroutineScope(Dispatchers.IO)
        // 监听蓝牙连接状态
        scope.launch {
            BLEHub.statusFlow.filter { it == BLEStatus.DISCONNECT }.collect {
                checkSelfJob?.cancel()
            }
        }
        // 监听设备状态
        scope.launch {
            BDCore.receiveProtoSharedFlow.filter { it.protocol::class == BDZJA_Data::class }
                .map { it.protocol }.map { it as BDZJA_Data }.collect {
                    checkSelfDataFlow.value = it
                }
        }
        scope.launch {
            BDCore.receiveProtoSharedFlow.filter { it.protocol::class == BDGGA_Data::class }
                .map { it.protocol }.map { it as BDGGA_Data }.collect { locationDataFlow.value = it }
        }
    }

    override fun instantOf(name: String): Boolean {
        return false
    }

    override fun getIconID(): Int {
        return R.mipmap.bd_image_h1301
    }

    override fun getProtoVersion(): ProtoVersion {
        return ProtoVersion.BD3
    }

    override fun getConnectSetting(): NotifySettingInfo {
        return NotifySettingInfo()
    }

    override suspend fun onDeviceConnected() {
        // 设置通讯频点
        BLEHub.sendCCLFN(CCLFN_Data(true, BDSendChannel.LF1))
        // 开启定时自检任务
        checkSelfJob = CoroutineScope(Dispatchers.IO).launch {
            launch {
                while (true) {
                    BLEHub.sendCCZJA(CCZJA_Data())
                    delay(1000 * 17)
                }
            }
            launch {
                while (true) {
                    // 启动位置输出
                    BLEHub.sendCCDWO(CCDWO_Data(true, 5))
                    delay(1000 * 5)
                }
            }
        }
    }

    override suspend fun setCenterCard(card: String) { }

    override fun getDeviceStatusDataListFlow(): Flow<List<BDDeviceStatusData>> {
        return checkSelfDataFlow.combine(locationDataFlow) { self, loc ->
            self.toBDDeviceStatusDataList() + loc.toBDDeviceStatusDataList()
        }.combine(Beidou.cardFlow) { list, card ->
            list + card.toBDDeviceStatusDataList()
        }
    }

    private fun BDZJA_Data?.toBDDeviceStatusDataList() = listOf(
        BDDeviceStatusData(
            BDDeviceStatusData.Type.BATTERY,
            "设备电量",
            if (this == null) "--" else "${battery.toStringWithMaxDecimal(2)}%(${powerStatus.text})"
        )
    )

    private fun BDGGA_Data?.toBDDeviceStatusDataList() = listOf(
        BDDeviceStatusData(
            BDDeviceStatusData.Type.LOCATION,
            "经纬度",
            if (this == null) "--" else
                "${latitude.toLatitudeString("Fd°m′S.ss″")},${longitude.toLongitudeString("Fd°m′S.ss″")}"
        ),
        BDDeviceStatusData(
            BDDeviceStatusData.Type.ALTITUDE,
            "高程",
            if (this == null) "--" else "${altitude}米"
        )
    )
}